import { ComponentFixture, fakeAsync, TestBed, waitForAsync } from '@angular/core/testing';
import { Component, Input, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core';
import { InputModule } from './input.module';
import { InputDirective } from './input.directive';
import { LvSizeLD } from '../core/api';

@Component({
  template: `
    <lv-input-group
      [lvSize]="lvGroupSize"
      [lvPrefix]="lvPrefix"
      [lvSuffix]="lvSuffix"
      [lvAddBefore]="lvAddBefore"
      [lvAddAfter]="lvAddAfter"
      [lvDisabled]="lvDisabled"
    >
      <input lv-input [lvSize]="lvSize" />
    </lv-input-group>
    <lv-input-lint>
      <textarea [lvAutosize]="lvAutosize" lvMaxLength="10" lv-input></textarea>
    </lv-input-lint>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
class TestInputComponent {
  @Input() lvSize: LvSizeLD = 'default';

  @Input() lvGroupSize: LvSizeLD = 'default';
  @Input() lvPrefix: string;
  @Input() lvSuffix: string;
  @Input() lvAddBefore: string;
  @Input() lvAddAfter: string;
  @Input() lvDisabled: boolean;

  @Input() lvAutosize: boolean | { maxRows: number; minRows: number } = false;
}

describe('InputComponent', () => {
  beforeEach(waitForAsync(() => {
    TestBed.configureTestingModule({
      declarations: [TestInputComponent, InputDirective],
      imports: [InputModule],
      teardown: { destroyAfterEach: true },
    }).compileComponents();
  }));

  describe('render', () => {
    let component: TestInputComponent;
    let fixture: ComponentFixture<TestInputComponent>;
    let cdr: ChangeDetectorRef;

    const renderComponent = param => {
      for (const [key, value] of Object.entries(param)) {
        component[key] = value;
      }
      fixture.detectChanges();
      expect(fixture).toMatchSnapshot();
    };

    const rerenderComponent = param => {
      for (const [key, value] of Object.entries(param)) {
        component[key] = value;
      }
      cdr.detectChanges();
      expect(fixture).toMatchSnapshot();
    };

    beforeEach(() => {
      fixture = TestBed.createComponent(TestInputComponent);
      component = fixture.componentInstance;
      cdr = fixture.debugElement.injector.get(ChangeDetectorRef);
    });

    // Input两种尺寸渲染，large和default
    it('with lvSize', () => {
      renderComponent({ lvSize: 'large' });
      rerenderComponent({ lvSize: 'default' });
      rerenderComponent({ lvGroupSize: 'large' });
    });

    // 内置前缀后缀渲染
    it('with lvPrefix/lvSuffix', () => {
      renderComponent({ lvPrefix: 'Https://', lvSuffix: '8080' });
    });

    // 外置前缀后缀渲染
    it('with lvAddBefore/lvAddAfter', () => {
      renderComponent({ lvAddBefore: 'speed', lvAddAfter: 'Mb/s' });
    });

    it('with lvAutosize', () => {
      renderComponent({ lvAutosize: true });
      rerenderComponent({ lvAutosize: { minRows: 2, maxRows: 6 } });
    });
  });

  describe('work', () => {
    let component: TestInputComponent;
    let fixture: ComponentFixture<TestInputComponent>;

    beforeEach(() => {
      fixture = TestBed.createComponent(TestInputComponent);
      component = fixture.componentInstance;
    });

    // disabled状态下input无法输入
    it('should not work when disabled', fakeAsync(() => {
      component.lvDisabled = true;
      fixture.detectChanges();

      const input = fixture.nativeElement.querySelector('.lv-input');
      input.value = 'test';
      input.dispatchEvent(new Event('input'));
      fixture.detectChanges();

      expect(input.textContent).not.toBe('test');
    }));
  });
});
